/*
 * Copyright 2022 FA-Software (Shanghai) Co., Ltd. All Rights Reserved.
 *
 * Licensed under the FA-Software License, Version 1.0;
 * https://www.fa-software.com/licenses/LICENSE-1.0
 */
package com.eric.study.reactor.commons.response;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

import java.io.Serial;
import java.io.Serializable;

/**
 * Response .
 *
 * <p>
 * change history:
 *
 * <pre>
 * date               defect            person            comments
 * --------------------------------------------------------------------------------
 * 2023/2/9 15:06    ********          Qiheng Zhang               create file.
 * </pre>
 *
 * @author Qiheng Zhang
 * @date 2023/2/9 15:06
 * @copyright 2023, FA Software (Shanghai) Co., Ltd. All Rights Reserved.
 * @since JDK1.8
 * @since 1.0.0
 */
@Setter
@Getter
@EqualsAndHashCode
@SuppressWarnings("unused")
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class Response implements Serializable {

    @Serial
    private static final long serialVersionUID = -8312634345924284950L;

    /**
     * 返回状态响应码
     */
    private int status;

    /**
     * 接口编号
     */
    @JsonIgnore
    private String transactionID = "";

    /**
     * 正常响应返回结果
     */
    private Object body;

    /**
     * 错误消息
     */
    private ResponseError errors;

    /**
     * 标识是否需要覆盖 {@link #status} 值，即决定是否可以调用 {@link #status(int)} 方法
     */
    @JsonIgnore
    private boolean coverStatus;

    private Response() {
        this.coverStatus = false;
    }

    private Response(boolean coverCodeFlag) {
        this.coverStatus = coverCodeFlag;
    }

    /**
     * 构建成功的消息返回体
     *
     * @return success response
     * @author Qiheng Zhang
     * @date 2023/6/6 17:32
     * @since 1.0.0
     */
    public static Response success() {
        final Response response = new Response(true);
        response.status = ResponseStatus.OK.getValue();
        response.coverStatus = false;
        return response;
    }

    /**
     * 构建成功的消息返回体
     *
     * @param body 返回结果
     * @return success response
     * @author Qiheng Zhang
     * @date 2023/6/6 17:33
     * @since 1.0.0
     */
    public static Response success(Object body) {
        return success().body(body);
    }

    /**
     * 构建失败的消息返回体
     *
     * @return error response
     * @author Qiheng Zhang
     * @date 2023/6/6 17:33
     * @since 1.0.0
     */
    public static Response failed() {
        return new Response(true).status(ResponseStatus.BAD_REQUEST.getValue());
    }

    /**
     * 构建失败的消息返回体
     *
     * @param status http 状态码
     * @return error response
     * @author Qiheng Zhang
     * @date 2023/6/6 17:34
     * @since 1.0.0
     */
    public static Response failed(int status) {
        return new Response(true).status(status);
    }

    /**
     * 设置返回消息响应体中的响应码。
     *
     * <p>
     * <font style="color:yellow">注意：</font> 如果操作成功，固定响应码为 <code>200</code>，其在创建 函数
     * {@link #success()} 和 {@link #success(Object)} 中已经添加，不需要再次调用此方法覆写
     *
     * <p>
     * <font style="color:yellow"> 即：此方法只能在 {@link #failed()} 方法后调用 </font>
     *
     * <p>
     * <br>
     *
     * @param code 响应码
     * @return 当前操作的 {@link Response} 实例对象
     * @author Qiheng Zhang
     * @date 2023/6/6 17:34
     * @since 1.0.0
     */
    public Response status(int code) {
        if (this.coverStatus) {
            this.status = code;
        }
        return this;
    }

    /**
     * 设置返回消息响应体中的 TX Id（接口编号）
     *
     * @param transactionID transaction id
     * @return 当前操作的 {@link Response} 实例对象
     * @author Qiheng Zhang
     * @date 2023/6/6 17:34
     * @since 1.0.0
     */
    public Response transactionId(String transactionID) {
        this.transactionID = transactionID;
        return this;
    }

    /**
     * 设置返回消息响应体中的详细内容。一般为查询结果
     *
     * @param data 查询结果
     * @return 当前操作的 {@link Response} 实例对象
     * @author Qiheng Zhang
     * @date 2023/6/6 17:34
     * @since 1.0.0
     */
    public Response body(Object data) {
        this.body = data;
        return this;
    }

    /**
     * 设置业务异常错误响应。
     *
     * @param responseError 异常信息
     * @return 当前操作的 {@link Response} 实例对象
     * @author Qiheng Zhang
     * @date 2023/6/7 16:55
     * @since 1.0.0
     */
    public Response responseError(ResponseError responseError) {
        this.errors = responseError;
        return this;
    }

    /**
     * 错误消息响应。
     * <p>
     * 当系统或者框架发生异常时，只会有错误信息，没有错误码的情况下可以调用此方法。
     *
     * @param errorMessage 系统或者框架异常信息
     * @return 当前操作的 {@link Response} 实例对象
     * @author Qiheng Zhang
     * @date 2023/6/7 16:55
     * @since 1.0.0
     */
    public Response responseError(String errorMessage) {
        this.errors = ResponseError.builder().system(errorMessage).build();
        return this;
    }

    /**
     * 重写 {@link Object#toString()} 方法
     *
     * @return json string for {@link Response}
     * @author Qiheng Zhang
     * @date 2023/6/6 17:34
     * @since 1.0.0
     */
    @Override
    public String toString() {
        return String.format("""
                {
                    "status":%d,
                    "error": "%s",
                    "body":%s
                }
                """, this.status, this.errors, this.body);
    }

}
